<script lang='ts' setup>
import { reactive, ref, toRaw, watch, } from 'vue';
import useTableMethods from './hooks/useTableMethods';
import useFieldMethods from './hooks/useFieldMethods';
import useWhereMethods from './hooks/useWhereMethods';
import useReBuildSql from './hooks/useReBuildSql';
import useOrderByMethods from './hooks/useOrderByMethods';
import HtmlReadonlyEditor from '@/components/HtmlReadonlyEditor/index.vue'
import { useUpdateMethods } from './hooks/useUpdateMethods';
import { useInsertMethods } from './hooks/useInsertMethods';
import _ from 'lodash';
const props = defineProps<{ tableName: string, backData?: any }>()
// const props = withDefaults(defineProps<{ tableName: string, backData?: any }>(), {
//   tableName: 'user'
// })
defineExpose({ onChange })

// 查询类型：select,update,delete,insert
const sqlStr = ref('')
const actionType = ref('')

const tableSelected = ref([])

//-----------字段相关-------------
const {
  fieldSelected,
  fieldSelectAllCheckBox,
  fieldSelectChange,
  fieldList
} = useFieldMethods(tableSelected)

//-----------字段相关结束-------------

//-----------表相关-------------

const {
  isMutilTable,
  tableSelectAssociation,
  selectAssociationTable,
  actionTypeList,
} = useTableMethods(fieldSelected, tableSelected)
//-----------表相关结束-------------

//-----------where查询语句-------------
const {
  whereSelectList,
  addWhereSelect,
  deleteWhereSelect,
  logicList,
  operatorList
} = useWhereMethods()
//-----------where查询语句结束-------------

//-----------Order by-------------
const {
  orderSelectList,
  addOrderSelect,
  deleteOrderSelect
} = useOrderByMethods()
//-----------Order by结束-------------


//-----------分页设置-------------
const isPage = ref(false)
const pageParamName = ref({
  pageNo: 'page',
  pageSize: 'perPage'
})
//-----------分页设置结束-------------

//-----------更新相关-------------
const {
  updateCheckBoxList,
  upDateFieldList,
  allUpdateCheckBox,
  changeUpdateAllCheckBox,
  initUpdateList,
} = useUpdateMethods(fieldList)
//-----------更新相关结束-------------

//-----------删除相关-------------
const physicsDelete = ref(false)
//-----------删除相关结束-------------

//-----------插入相关-------------
const {
  allInsertCheckBox,
  insertCheckBoxList,
  insertFieldList,
  changeInsertAllCheckBox,
  initInsertList
} = useInsertMethods(fieldList);
//-----------插入相关结束-------------



//-----------构建sql语句相关-------------

const {
  // formatSql,
  reBuildSql
} = useReBuildSql(
  // 查询
  whereSelectList,
  actionType,
  fieldSelected,
  tableSelectAssociation,
  isMutilTable,
  sqlStr,
  orderSelectList,
  fieldList,
  // 更新
  updateCheckBoxList,
  upDateFieldList,
  // 删除
  physicsDelete,
  // 插入
  insertCheckBoxList,
  insertFieldList,
)
//-----------构建sql语句相关结束-------------

//-----------构建和onChange事件-------------
/**
 * 将对象转换为普通对象
 *
 * @param obj 待转换的对象
 * @returns 返回转换后的普通对象
 */
function toPlainObject(obj: any) {
  if (reactive(obj)) {
    obj = toRaw(obj);
  }
  for (let key in obj) {
    if (typeof obj[key] === 'object' && obj[key] !== null) {
      obj[key] = toPlainObject(obj[key]);
    }
  }
  return obj;
}

function onChange() {
  let o = {} as any
  if (actionType.value == 'select' || actionType.value == 'selectOne') {
    o = {
      rawScript: sqlStr.value,
      saveScript: sqlStr.value.replace(/<br\/>|&emsp;/g, ''), // 去掉换行符
      actionType: actionType.value,
      isPage: isPage.value,
      pageParamName: toPlainObject(pageParamName.value),
      fieldSelected: toPlainObject(fieldSelected.value),
      whereSelectList: toPlainObject(whereSelectList.value),
      orderSelectList: toPlainObject(orderSelectList.value),
    }
    if (actionType.value == 'selectOne') {
      delete o.isPage
    }
  }
  if (actionType.value == 'update') {
    o = {
      rawScript: sqlStr.value,
      saveScript: sqlStr.value.replace(/<br\/>|&emsp;/g, ''), // 去掉换行符
      actionType: actionType.value,
      whereSelectList: toPlainObject(whereSelectList.value),
      updateCheckBoxList: toPlainObject(updateCheckBoxList.value),
      upDateFieldList: toPlainObject(upDateFieldList.value),
    }
  }
  if (actionType.value == 'delete') {
    o = {
      actionType: actionType.value,
      rawScript: sqlStr.value,
      saveScript: sqlStr.value.replace(/<br\/>|&emsp;/g, ''), // 去掉换行符
      physicsDelete: physicsDelete.value,
      whereSelectList: toPlainObject(whereSelectList.value),
    }
  }
  if (actionType.value == 'insert') {
    o = {
      rawScript: sqlStr.value,
      actionType: actionType.value,
      saveScript: sqlStr.value.replace(/<br\/>|&emsp;/g, ''), // 去掉换行符
      allInsertCheckBox: toPlainObject(allInsertCheckBox.value),
      insertCheckBoxList: toPlainObject(insertCheckBoxList.value),
      insertFieldList: toPlainObject(insertFieldList.value),
      whereSelectList: toPlainObject(whereSelectList.value),
    }
  }
  return o
}

watch(() => [
  fieldSelected.value,
  actionType.value,
  tableSelected.value,
  tableSelectAssociation.value,
  whereSelectList.value,
  orderSelectList.value,
  isPage.value,
  pageParamName.value,
  // update
  updateCheckBoxList,
  upDateFieldList,
  // 删除
  physicsDelete,
  // 插入
  insertCheckBoxList,
  insertFieldList,
], () => {

  reBuildSql()
  // onChange()
}, {
  deep: true
})

//-----------构建和onChange事件结束-------------



watch(() => props.tableName, () => {
  tableSelectAssociation.value[0].tableA = props.tableName
  tableSelected.value = [props.tableName] as any

  selectAssociationTable(props.tableName)
}, {
  immediate: true,
})

watch(() => fieldList.value, (val) => {
  if (val && val.length > 0) {
    initUpdateList()
    initInsertList()
  }
}, {
  immediate: true,
  deep: true
})

// 回填数据
watch(() => props.backData, (val) => {
  if (val && (typeof val == 'object') && Object.keys(props.backData).length > 0) {
    let db = _.cloneDeep(props.backData);
    actionType.value = db.actionType;// 查询类型：select,update,delete,insert
    whereSelectList.value = db.whereSelectList ? db.whereSelectList : []; // where条件

    if (db.actionType == 'select' || db.actionType == 'selectOne') {
      pageParamName.value = db.pageParamName ?
        db.pageParamName : {
          pageNo: 'page',
          pageSize: 'perPage'
        }; // 分页参数名称
      isPage.value = db.isPage ? db.isPage : false; // 是否分页
      sqlStr.value = db.rawScript ? db.rawScript : ''; // 原始sql语句
      if (db.fieldSelected && db.fieldSelected.length > 0) {
        // let o = _.cloneDeep(fieldSelected.value);
        fieldSelected.value[0] = db.fieldSelected[0]
        // Object.keys(o).forEach((key: any) => {
        //   if (!fieldSelected.value[key]) {
        //     fieldSelected.value[key] = o[key]
        //   }
        // })
      }
      orderSelectList.value = db.orderSelectList ? db.orderSelectList : []; // 排序条件
    }
    if (db.actionType == 'update') {
      allUpdateCheckBox.value = db.allUpdateCheckBox ? db.allUpdateCheckBox : false; // 是否全选

      // if (db.upDateFieldList && db.upDateFieldList.length > 0) {
      //   let o = _.cloneDeep(upDateFieldList.value);
      //   upDateFieldList.value = db.upDateFieldList
      //   Object.keys(o).forEach((key) => {
      //     if (!upDateFieldList.value[key]) {
      //       upDateFieldList.value[key] = o[key]
      //     }
      //   })
      // }
      updateCheckBoxList.value = db.updateCheckBoxList ? db.updateCheckBoxList : [] // 更新的字段勾选状态; 
    }
    if (db.actionType == 'delete') {
      physicsDelete.value = db.physicsDelete ? db.physicsDelete : false; // 是否物理删除
    }
    if (db.actionType == 'insert') {
      allInsertCheckBox.value = db.allInsertCheckBox ? db.allInsertCheckBox : false; // 是否全选
      // if (db.insertFieldList && db.insertFieldList.length > 0) {
      //   let o = _.cloneDeep(insertFieldList.value);
      //   insertFieldList.value = db.insertFieldList;// 插入的字段列表; 每个字段都有别名和是否为参数标记
      //   Object.keys(o).forEach((key) => {
      //     if (!insertFieldList.value[key]) {
      //       insertFieldList.value[key] = o[key]
      //     }
      //   })
      // }
      insertCheckBoxList.value = db.insertCheckBoxList ? db.insertCheckBoxList : []// 选择的字段勾选状态; 
    }
  }
}, {
  immediate: true,
  deep: true
})

</script>
<template>
  <div class="s">
    <!-- 左边的选择器编辑器 -->
    <div class="s_left">
      <!-- 选择增删改查类型 选择表和关联类型 -->
      <!-- 查询 -->
      <span v-if="actionType == 'select' || actionType == 'selectOne'">
        <!-- select fields -->
        <div class="jk_card" style="">
          <div class="jk_card_header" style="background:#67C23A;">
            <span>查询字段</span>
          </div>
          <div class="jk_card_body">
            <div class="jk_card_body_list" v-for="(field, index) in fieldList">
              <div class="selectFieldList">
                <!-- <span>{{ field.label }}&nbsp;</span> -->
                <el-select size="small" @change="fieldSelectChange($event, index, field.fields)"
                  v-model="fieldSelected[index].fields" multiple placeholder="请选择">
                  <el-option :label="i.label" :value="i.value" v-for="i in field.fields"></el-option>
                </el-select>&nbsp;
                <el-checkbox @change="fieldSelectAllCheckBox($event, index)"
                  v-model="fieldSelected[index].isSelectAllField">全选</el-checkbox>
                <el-button size="small" :icon="fieldSelected[index].isExpand ? 'ArrowUp' : 'ArrowDown'" link
                  type="primary" @click="fieldSelected[index].isExpand = !fieldSelected[index].isExpand">别名</el-button>
              </div>
              <div class="selectFieldListInput" v-for="aliasField in fieldSelected[index].fieldAliasNameMapArray"
                v-if="fieldSelected[index].isExpand">
                <span class="selectFieldListInputName" :title="aliasField.name">
                  <span>{{ aliasField.name }}</span>
                </span>
                <el-input size="small" placeholder="别名" v-model="aliasField.aliasName" />&nbsp;
              </div>
            </div>
            <div v-if="!fieldList.length" class="noDataText">先填写表名</div>
          </div>
        </div>
        <!-- where -->
        <div class="jk_card" style="margin-top: 20px;">
          <div class="jk_card_header" style="background:#E6A23C;">
            <span>WHERE条件</span>
            <el-button icon="Plus" link style="color: white;" @click="addWhereSelect">添加条件</el-button>
          </div>
          <div class="jk_card_body">
            <div v-for="(item, index) in whereSelectList" class="whereBox">
              <div v-if="index > 0" class="whereBoxLogic">
                <el-select size="small" placeholder="请选择" v-model="item.logic" class="oaa">
                  <el-option v-for="i in logicList" :key="i.value" :label="i.label" :value="i.value"></el-option>
                </el-select>
              </div>
              <div class="whereSelect">
                <div class="whereSelectList">
                  <el-select style="width:300px;margin-right:5px" size="small" separator="." v-model="item.field">
                    <el-option v-for="i in fieldList[0].fields" :key="i.value" :label="i.label"
                      :value="i.value"></el-option>
                  </el-select>
                  <el-select size="small" placeholder="请选择" v-model="item.operator">
                    <el-option v-for="i in operatorList" :key="i.value" :label="i.label" :value="i.value"></el-option>
                  </el-select>
                </div>
                <div class="segBox" v-if="item.operator != 'IS NULL' && item.operator != 'IS NOT NULL'" style="">
                  <div class="seglabel">输入值作为：</div>
                  <el-segmented style="font-size:13px" size="small" v-model="item.isParamName"
                    :options="[{ label: '查询参数名', value: true, }, { label: '常量', value: false, }]" />
                </div>
                <div class="whereSelectList" v-if="item.operator != 'IS NULL' && item.operator != 'IS NOT NULL'">
                  <el-input size="small" :placeholder="item.operator == 'IN' ? '请输入值，多个值用英文逗号分隔' : '请输入值'"
                    v-model="item.valueA"></el-input>
                  <div class="tableRelation_list_text" v-if="item.operator == 'BETWEEN'">AND</div>
                  <el-input size="small" v-if="item.operator == 'BETWEEN'"
                    :placeholder="item.operator == 'IN' ? '请输入值，多个值用英文逗号分隔' : '请输入值'" v-model="item.valueB"></el-input>
                </div>
                <el-icon size="18" @click="deleteWhereSelect(index)" color="red" class="tableRelation_list_delete">
                  <CircleClose />
                </el-icon>
              </div>
            </div>
            <div class="noDataText" v-if="!whereSelectList.length">请添加条件</div>
          </div>
        </div>
        <!-- order by -->
        <div class="jk_card" style="margin-top: 20px;">
          <div class="jk_card_header" style="background:#66c03b;">
            <span>ORDER BY</span>
            <el-button icon="Plus" link style="color: white;" @click="addOrderSelect">添加排序</el-button>
          </div>
          <div class="jk_card_body">
            <div v-for="(item, index) in orderSelectList" class="whereSelect" style="margin-right:20px;display:flex;">
              <el-select style="width:300px;margin-right:5px" size="small" v-model="item.field">
                <el-option v-for="i in fieldList[0].fields" :key="i.value" :label="i.label"
                  :value="i.value"></el-option>
              </el-select>
              <el-select size="small" placeholder="请选择" v-model="item.orderType">
                <el-option label="升序" value="ASC"></el-option>
                <el-option label="降序" value="DESC"></el-option>
              </el-select>
              <el-icon size="18" @click="deleteOrderSelect(index)" color="red" class="tableRelation_list_delete">
                <CircleClose />
              </el-icon>
            </div>
            <div class="noDataText" v-if="!orderSelectList.length">请添加排序</div>
          </div>
        </div>
        <!-- 分页 -->
        <div class="jk_card" style="margin-top: 20px;" v-if="actionType == 'select'">
          <div class="jk_card_header" style="background:#909399;">
            <span>分页配置</span>
          </div>
          <div class="jk_card_body">
            <el-switch v-model="isPage" size="small" active-text="开启分页" inactive-text="关闭分页"></el-switch>
            <div v-if="isPage">
              <div class="segBox">
                <span class="seglabel">页号参数名：</span>
                <el-input size="small" style="width:200px;" placeholder="请输入页号参数名"
                  v-model="pageParamName.pageNo"></el-input>
              </div>
              <div class="segBox">
                <span class="seglabel">每页条数参数名：</span>
                <el-input size="small" style="width:200px;" placeholder="请输入每页条数参数名"
                  v-model="pageParamName.pageSize"></el-input>
              </div>
            </div>
          </div>
        </div>
      </span>
      <!-- 更新 -->
      <span v-if="actionType == 'update'">
        <!-- 选择字段 -->
        <div class="jk_card" style="">
          <div class="jk_card_header" style="background:#67C23A;">
            <span>更新字段</span>
          </div>
          <div class="jk_card_body">
            <el-checkbox size="small" style="margin-left: 8px;" label="全选" v-model="allUpdateCheckBox"
              @change="changeUpdateAllCheckBox" />
            <el-checkbox-group v-if="upDateFieldList.length > 0" v-model="updateCheckBoxList">
              <div v-for="(fItem, index) in fieldList[0].fields" class="whereSelect" style=" display:flex;height:40px">
                <el-checkbox size="small" :label="fItem.label" :value="fItem.value">
                  <template v-slot>
                    <div :title="fItem.label" class="insertFieldLabel">{{ fItem.label }}</div>
                  </template>
                </el-checkbox>
                <el-input size="small" style="margin-left:10px;" placeholder="请输入值"
                  v-model="upDateFieldList[index].aliasName"></el-input>
                <el-segmented size="small" style="font-size:13px;margin-left:10px;"
                  v-model="upDateFieldList[index].isParamName"
                  :options="[{ label: '参数名', value: true, }, { label: '常量', value: false, }]" />
              </div>
            </el-checkbox-group>
          </div>
        </div>
        <!-- where -->
        <div class="jk_card" style="margin-top: 20px;">
          <div class="jk_card_header" style="background:#E6A23C;">
            <span>WHERE条件</span>
            <el-button icon="Plus" link style="color: white;" @click="addWhereSelect">添加条件</el-button>
          </div>
          <div class="jk_card_body">
            <div v-for="(item, index) in whereSelectList" class="whereBox">
              <div v-if="index > 0" class="whereBoxLogic">
                <el-select size="small" placeholder="请选择" v-model="item.logic" class="oaa">
                  <el-option v-for="i in logicList" :key="i.value" :label="i.label" :value="i.value"></el-option>
                </el-select>
              </div>
              <div class="whereSelect">
                <div class="whereSelectList">
                  <el-select style="width:300px;margin-right:5px" size="small" separator="." v-model="item.field">
                    <el-option v-for="i in fieldList[0].fields" :key="i.value" :label="i.label"
                      :value="i.value"></el-option>
                  </el-select>
                  <el-select size="small" placeholder="请选择" v-model="item.operator">
                    <el-option v-for="i in operatorList" :key="i.value" :label="i.label" :value="i.value"></el-option>
                  </el-select>
                </div>
                <div class="segBox" style="" v-if="item.operator != 'IS NULL' && item.operator != 'IS NOT NULL'">
                  <div class="seglabel">输入值作为：</div>
                  <el-segmented style="font-size:13px" size="small" v-model="item.isParamName"
                    :options="[{ label: '查询参数名', value: true, }, { label: '常量', value: false, }]" />
                </div>
                <div class="whereSelectList" v-if="item.operator != 'IS NULL' && item.operator != 'IS NOT NULL'">
                  <el-input size="small" :placeholder="item.operator == 'IN' ? '请输入值，多个值用英文逗号分隔' : '请输入值'"
                    v-model="item.valueA"></el-input>
                  <div class="tableRelation_list_text" v-if="item.operator == 'BETWEEN'">AND</div>
                  <el-input size="small" v-if="item.operator == 'BETWEEN'"
                    :placeholder="item.operator == 'IN' ? '请输入值，多个值用英文逗号分隔' : '请输入值'" v-model="item.valueB"></el-input>
                </div>
                <el-icon size="18" @click="deleteWhereSelect(index)" color="red" class="tableRelation_list_delete">
                  <CircleClose />
                </el-icon>
              </div>
            </div>
            <div class="noDataText" v-if="!whereSelectList.length">请添加条件</div>
          </div>
        </div>
      </span>
      <!-- 删除 -->
      <span v-if="actionType == 'delete'">
        <!-- where -->
        <div class="jk_card" style=" ">
          <div class="jk_card_header" style="background:#E6A23C;">
            <span>WHERE条件</span>
            <el-button icon="Plus" link style="color: white;" @click="addWhereSelect">添加条件</el-button>
          </div>
          <div class="jk_card_body">
            <div v-for="(item, index) in whereSelectList" class="whereBox">
              <div v-if="index > 0" class="whereBoxLogic">
                <el-select size="small" placeholder="请选择" v-model="item.logic" class="oaa">
                  <el-option v-for="i in logicList" :key="i.value" :label="i.label" :value="i.value"></el-option>
                </el-select>
              </div>
              <div class="whereSelect">
                <div class="whereSelectList">
                  <el-select style="width:300px;margin-right:5px" size="small" separator="." v-model="item.field">
                    <el-option v-for="i in fieldList[0].fields" :key="i.value" :label="i.label"
                      :value="i.value"></el-option>
                  </el-select>
                  <el-select size="small" placeholder="请选择" v-model="item.operator">
                    <el-option v-for="i in operatorList" :key="i.value" :label="i.label" :value="i.value"></el-option>
                  </el-select>
                </div>
                <div class="segBox" style="" v-if="item.operator != 'IS NULL' && item.operator != 'IS NOT NULL'">
                  <div class="seglabel">输入值作为：</div>
                  <el-segmented style="font-size:13px" size="small" v-model="item.isParamName"
                    :options="[{ label: '查询参数名', value: true, }, { label: '常量', value: false, }]" />
                </div>
                <div class="whereSelectList" v-if="item.operator != 'IS NULL' && item.operator != 'IS NOT NULL'">
                  <el-input size="small" :placeholder="item.operator == 'IN' ? '请输入值，多个值用英文逗号分隔' : '请输入值'"
                    v-model="item.valueA"></el-input>
                  <div class="tableRelation_list_text" v-if="item.operator == 'BETWEEN'">AND</div>
                  <el-input size="small" v-if="item.operator == 'BETWEEN'"
                    :placeholder="item.operator == 'IN' ? '请输入值，多个值用英文逗号分隔' : '请输入值'" v-model="item.valueB"></el-input>
                </div>
                <el-icon size="18" @click="deleteWhereSelect(index)" color="red" class="tableRelation_list_delete">
                  <CircleClose />
                </el-icon>
              </div>
            </div>
            <div class="noDataText" v-if="!whereSelectList.length">请添加条件</div>
          </div>
        </div>
      </span>
      <!-- 添加 -->
      <span v-if="actionType == 'insert'">
        <!-- 选择字段 -->
        <div class="jk_card" style=" ">
          <div class="jk_card_header" style="background:#67C23A;">
            <span>插入字段</span>
          </div>
          <div class="jk_card_body">
            <el-checkbox size="small" label="全选" style="margin-left: 8px;" v-model="allInsertCheckBox"
              @change="changeInsertAllCheckBox" />
            <el-checkbox-group v-if="insertFieldList.length > 0" v-model="insertCheckBoxList">
              <div v-for="(fItem, index) in fieldList[0].fields" class="whereSelect" style=" display:flex;height:40px">
                <el-checkbox size="small" :label="fItem.label" :value="fItem.value">
                  <template v-slot>
                    <div :title="fItem.label" class="insertFieldLabel">{{ fItem.label }}</div>
                  </template>
                </el-checkbox>
                <el-input size="small" style="margin-left:10px;" placeholder="请输入值"
                  v-model="insertFieldList[index].aliasName"></el-input>
                <el-segmented size="small" style="font-size:13px;margin-left:10px;"
                  v-model="insertFieldList[index].isParamName"
                  :options="[{ label: '参数名', value: true, }, { label: '常量', value: false, }]" />
              </div>
            </el-checkbox-group>
          </div>
        </div>
      </span>
    </div>
    <!-- 预览编辑器 -->
    <div class="s_right">
      <div class="jk_card">
        <div class="jk_card_header">脚本预览</div>
        <div class="jk_card_body" style="padding: 0;background:#1e1e1e; ">
          <!-- <monaco-editor style="width:100%;height:500px;" language="txt" v-model="sqlStr" /> -->
          <html-readonly-editor v-model="sqlStr" />
          <!-- <div class="editorFooter">
            <el-button type="" style="" @click="reBuildSql">重新生成脚本</el-button>
          </div> -->
        </div>
      </div>
    </div>
  </div>

</template>
<style scoped lang='scss'>
@use"./index.scss" as *;
</style>